using System;
using System.ComponentModel;
using System.Drawing;
using SdlDotNet.Core;
using SdlDotNet.Graphics;
using SdlDotNet.Graphics.Primitives;
using SpaceTrader.Core;

namespace Core
{
    [DefaultProperty("Name")]
    public class GameObject
    {
        private Color mColor = Color.White;
        private float mMaxSpeed = 0;
        private Vector mMovementVector = Vector.FromDirection(0, 0);
        private String mName = "";
        private Point mPosition = new Point(0, 0);
        private int mRotation = 0;
        private int mRotationSpeed = 0;
        private float mSpeed = 0;
        private float mThrottle = 0;
        private float mThrust = 0;

        public GameObject(int x, int y)
        {
            Position = new Point(x, y);
            Logger.Instance().Log(string.Format("{0} created.", GetType().Name), LogLevel.Debug);
        }

        public GameObject(int x, int y, string name) : this(x, y)
        {
            Name = name;
        }

        [Category("Appearance")]
        [Description("The name to display for this object.")]
        public String Name
        {
            get { return mName; }
            set { mName = value; }
        }

        [Category("Appearance")]
        public Color ForeColor
        {
            get { return mColor; }
            set { mColor = value; }
        }

        [Category("Movement")]
        [Description("The object's location in space.")]
        public Point Position
        {
            get { return mPosition; }
            set { mPosition = value; }
        }

        [Category("Movement")]
        [Description("The object's rotation. 0 = Right")]
        public int Rotation
        {
            get { return mRotation; }
            set
            {
                if (value < 0)
                    value = 360 + value;
                else if (value > 359)
                    value = value - 360;

                mRotation = value;
            }
        }

        [Category("Movement")]
        [Description("The speed the object is turing at in degrees.")]
        public int RotationSpeed
        {
            get { return mRotationSpeed; }
            set { mRotationSpeed = value; }
        }

        [Category("Movement")]
        public float Throttle
        {
            get { return mThrottle; }
            set
            {
                if (value > 1.0F || value < 0.0F)
                    throw new OverflowException("Throttle must be a float between 0 and 1.");

                mThrottle = value;
            }
        }

        [Category("Movement")]
        public float Thrust
        {
            get { return mThrust; }
            set { mThrust = value; }
        }

        public float Speed
        {
            get { return mSpeed; }
            set { mSpeed = value; }
        }

        public float MaxSpeed
        {
            get { return mMaxSpeed; }
            set { mMaxSpeed = value; }
        }

        public Vector MovementVector
        {
            get { return mMovementVector; }
        }

        public virtual void Update()
        {
            UpdateVector();
            UpdatePosition();
            UpdateRotation();
        }

        private void UpdateVector()
        {
            if (Throttle > 0.0f)
            {
                if (Speed < MaxSpeed)
                    Speed += Thrust*Throttle;

                mMovementVector.Length = Speed;
                mMovementVector.DirectionDeg = Rotation;
            }
            else
            {
                if (Speed > 0)
                    Speed = Speed - 0.1f;

                mMovementVector.Length = Speed;
            }
        }

        private void UpdateRotation()
        {
            Rotation = Rotation + RotationSpeed;
        }

        private void UpdatePosition()
        {
            Vector Pos = new Vector(Position);

            Pos = Pos + MovementVector;
            Pos.X = (float) Math.Round(Pos.X);
            Pos.Y = (float) Math.Round(Pos.Y);

            Position = Pos.Point;
        }

        public virtual Surface Render()
        {
            Surface surf = new Surface(20, 20);

            Box ObjectBox = new Box(new Point(0, 0), new Point(10, 10));
            surf.Draw(ObjectBox, ForeColor, false, true);

            return surf;
        }

        public virtual bool Hit(Point p)
        {
            if (p.X > Position.X - 10 && p.Y > Position.Y - 10 && p.X < Position.X + 10 && p.Y < Position.Y + 10)
                return true;

            return false;
        }

        public virtual Polygon GetPolygon()
        {
            return new Polygon();
        }

        public override string ToString()
        {
            return "Object " + Name + " ";
        }
    }
}